package com.easyboot.framework.exception;

import cn.hutool.core.util.StrUtil;
import com.easyboot.utils.log.LoggerHelper;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * @author yushuo
 * @className
 * @descripton 使用RestControllerAdvice返回结果会自动转为json，否则请使用ExceptionPreHandleInterceptor 配置判断请求
 * @date 2021/2/2 16:52
 **/
//@Slf4j
@ControllerAdvice
public class EasyExceptionHandler {

    /**
     * @author yushuo
     * @description 授权异常
     * @date 11:28 2021/2/3
     * @param e, req
     * @return java.lang.Object
     **/
    @ExceptionHandler(UnauthorizedException.class)
    public Object handleAuthException(UnauthorizedException e, HttpServletRequest req){
        //授权异常

        LoggerHelper.console("UnauthorizedException");
        if(isAjaxRequest(req)){
            ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
            modelAndView.addObject("message", e.getMessage());
            modelAndView.addObject("code",403);
            modelAndView.addObject("status",false);
            return modelAndView;
        }else{
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("msg", e.getMessage());
            modelAndView.addObject("url", req.getRequestURL());
            modelAndView.setViewName("error/unauth");
            return modelAndView;
        }
    }

    /**
     * @author yushuo
     * @description 授权异常
     * @date 11:28 2021/2/3
     * @param e, req
     * @return java.lang.Object
     **/
    @ExceptionHandler(AuthenticationException.class)
    public Object handleAuthException(AuthenticationException e, HttpServletRequest req){
        //授权异常

        LoggerHelper.console("AuthenticationException");
        if(isAjaxRequest(req)){
            ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
            modelAndView.addObject("message", e.getMessage());
            modelAndView.addObject("code",403);
            modelAndView.addObject("status",false);
            return modelAndView;
        }else{
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("msg", e.getMessage());
            modelAndView.addObject("url", req.getRequestURL());
            modelAndView.setViewName("error/unauth");
            return modelAndView;
        }
    }

    /**
     * @author yushuo
     * @description 授权异常
     * @date 11:28 2021/2/3
     * @param e, req
     * @return java.lang.Object
     **/
    @ExceptionHandler(TokenException.class)
    public Object handleTokenException(Exception e, HttpServletRequest req){
        //授权异常
        LoggerHelper.console("TokenException");

        if(isAjaxRequest(req)){
            ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
            modelAndView.addObject("message", e.getMessage());
            modelAndView.addObject("code",403);
            modelAndView.addObject("status",false);
            return modelAndView;
        }else{
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("msg", e.getMessage());
            modelAndView.addObject("url", req.getRequestURL());
            modelAndView.setViewName("error/unauth");
            return modelAndView;
        }
    }

    /**
     * @author yushuo
     * @description 系统异常
     * @date 11:28 2021/2/3
     * @param e, req
     * @return java.lang.Object
     **/
    @ExceptionHandler(EasyException.class)
    public Object handleEasyException(Exception e, HttpServletRequest req, HttpServletResponse response){
        //业务异常
        LoggerHelper.error("EasyException",e);

        if(isAjaxRequest(req)){
            ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
            modelAndView.addObject("message", e.getMessage());
            modelAndView.addObject("code",500);
            modelAndView.addObject("status",false);
            return modelAndView;
        }else{
            response.setStatus(500);
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("msg", e.getMessage());
            modelAndView.addObject("url", req.getRequestURL());
            modelAndView.setViewName("error/500");
            return modelAndView;
        }
    }

    /**
     * @author yushuo
     * @description 系统异常
     * @date 11:28 2021/2/3
     * @param e, req
     * @return java.lang.Object
    **/
    @ExceptionHandler(Exception.class)
    public Object handleException(Exception e, HttpServletRequest req, HttpServletResponse response){
        //业务异常
        LoggerHelper.error("Exception",e);

        response.setStatus(500);
        if(isAjaxRequest(req)){
            ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
            modelAndView.addObject("message", e.getMessage());
            modelAndView.addObject("code",500);
            modelAndView.addObject("status",false);
            return modelAndView;
        }else{
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("msg", e.getMessage());
            modelAndView.addObject("url", req.getRequestURL());
            modelAndView.setViewName("error/500");
            return modelAndView;
        }
    }

    /**
     * @author yushuo
     * @description 运行时异常
     * @date 11:28 2021/2/3
     * @param e, req
     * @return java.lang.Object
     **/
    @ExceptionHandler(RuntimeException.class)
    public Object notFount(RuntimeException e, HttpServletRequest req, HttpServletResponse response){
        //log.error("RuntimeException.异常信息：{}",e);

        LoggerHelper.error("RuntimeException",e);

        response.setStatus(500);

        if(isAjaxRequest(req)){
            ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
            modelAndView.addObject("message", e.getMessage());
            modelAndView.addObject("code",500);
            modelAndView.addObject("status",false);
            modelAndView.addObject("stackTrace", e.toString());

            return modelAndView;
        }else{
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("message", e.getMessage());
            modelAndView.addObject("url", req.getRequestURL());
            modelAndView.setViewName("error/500");
            return modelAndView;
        }
    }

    /**
     * 是否是Ajax异步请求
     *
     * @param
     */
    private boolean isAjaxRequest(HttpServletRequest httpServletRequest) {
        String accept = httpServletRequest.getHeader("accept");
        if (accept != null && accept.contains("application/json")) {
            return true;
        }

        String xRequestedWith = httpServletRequest.getHeader("X-Requested-With");
        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) {
            return true;
        }

        String uri = httpServletRequest.getRequestURI();
        if (StrUtil.containsAnyIgnoreCase(uri, ".json", ".xml")) {
            return true;
        }

        String ajax = httpServletRequest.getParameter("__ajax");
        if (StrUtil.containsAnyIgnoreCase(ajax, "json", "xml")) {
            return true;
        }
        return false;
    }

}
